# -*- coding: utf-8 -*-

'''
todo rename resource->resources
模仿eclipse资源数形式,比较复杂,现在还是倾向于构造一个实体树，而不是一个值对象数
值对象树测试中，某个获取到的节点只是节点的瞬间,不能持久依赖
'''

import resource_type

import pystore.core.framework.job as job
import pystore.core.framework.util as util
import pystore.core.framework.path as path
from pystore.core.framework.path import Path2
from pystore.core.framework.data_tree import DataTree

class ResourceChangeEvent(object):
    ''''''
    def __init__(self,source,delta):
        self.source=source
        self.delta=delta

class IStoreManager(object):
    '''示意接口'''
    def createProject(self,project,projectAttributes):
        '''
        createProject(Project project,dict resourceAttributes) -> _ResourceInfo
        '''
    def getFileStore(self,resource):
        '''getFileStore(Resource resource) -> FileStore'''
        
    def getProjectStores(self):
        '''getProjectStores() -> FileStore[]'''
        
class _ResourceInfo(object):
    def __init__(self,type):
        self.type = type #resource_type
        
        #file resource info
        self.fileModifyTime = -1
        self.fileSize = -1
        self.fileHash = ''
        
    @staticmethod
    def create(type,fileInfo):
        '''
        create(resource_type type,FileInfo fileInfo) -> _ResourceInfo
        '''
        result=_ResourceInfo(type)
        result.fileModifyTime = fileInfo.modifyTime
        result.fileSize = fileInfo.size
        result.fileHash = fileInfo.hash
        
        return result
class Workspace(object):
    def __init__(self,storeManager):
        self._storeManager = storeManager

        self._tree = DataTree(_ResourceInfo(resource_type.ROOT))
        self._root=resource_type.ROOT.newResource(Path2.ROOT,self)
        
    def _getResourceInfo(self,path):
        return self._tree.getData(path)
        
    def getRoot(self):
        '''
        getRoot() -> RootResource
        '''
        return self._root
    
    def exists(self,path):
        '''
        exists(path) -> bool
        
         资源树中是否存在此节点, 可能和底层文件系统中的实际状态不同
        '''
        return self._tree.exists(path)
    
    def _loadChildren(self,resource):
        childrenPath = self._tree.getChildrenPath(resource.getPath())
        return map(lambda path:self._loadResource(path) , childrenPath)
    
    def _loadResource(self,path):
        info = self._getResourceInfo(path)
        return info.type.newResource(path,self)
    
    def _newResource(self,type,path):
        pass
    
    def _create(self,path,resourceInfo):
        '''
       _create(self,Resource resource,_ResourceInfo resourceInfo)
        
        把资源信息添加到资源树
        '''
        self._tree.add(path,resourceInfo)
    
    
    
    def addResourceListener(self,listenerFunc):
        '''
        addResourceListener(self,func listenerFunc)
        
        args:
          listenerFunc: onResourceChange(ResourceChangeEvent event)
        '''
    
    def run(self,executeAroundMethod,monitor=job.DefaultMonitor()):
        '''
        run(self,func executeAroundMethod,IMonitor monitor)
        
         批量运行:只在运行完成后生成一次ChangeEvent
        '''
   
class Resource(object):
    
    def __init__(self,path,workspace):
        self._path = path
        self._workspace = workspace
    
    def isRoot(self):
        return self._workspace.getRoot() == self
    
    def __cmp__(self,other):
        return cmp(self._path ,other._path)
    
    def __hash__(self):
        return hash(self._path)
    
    def refresh(self):
        self._workspace._storeManager.refresh(self)
        
    def getWorkspace(self):
        return self._workspace
    
    def getPath(self):
        return self._path
    

    def exists(self):
        return self._workspace.exists(self._path)
    
    def getName(self) :
        if self._path == Path2.ROOT:
            return 'root'
        return self._path.getLastSegment();

    def getType(self):
        raise NotImplementedError

    def walk(self,walkFunc,fromTopToBottom=True):
        def getChildrenFunc(node):
            return [] if node.getType() == resource_type.FILE else node.getChildren()
        util.walkFunc(getChildrenFunc)(self,walkFunc,fromTopToBottom)
    

    def getParent(self):
        assert self.getType() != resource_type.ROOT
        
        if self.getType() == resource_type.PROJECT:
            return self._workspace.getRoot()
        if self._path.getSegmentsCount() == 2:
            return self._workspace.getRoot().getProject(self._path.getSegment(0))
        return Dir(self._path.removeLastSegments(1),self._workspace)
    
    def getProject(self):
        assert self.getType() != resource_type.ROOT
        if self.getType() == resource_type.PROJECT:
            return self
        return self.getParent().getProject()
   

    def refresh2(self):
        store = self._getFileStore()
        if store is None :#会不会store is None and self.exists()
            return 
        
        fileInfo = store.fetchInfo()
        #todo if fileInfo.exists = False not exists,del from tree
        resourceInfo=_ResourceInfo.create(self.getType(), fileInfo)
        
        if self._workspace._tree.exists(path):
            self._workspace._tree.update(self._path,resourceInfo)
        else:
            self._workspace._tree.add(self._path,resourceInfo)
        
        if fileInfo.isFile :
            return 
        for child in store.getChildren():
            fileInfo = child.fetchInfo()
            if fileInfo.isDir : 
                self.getDir(child.getName()).refresh2()
                continue 
            if fileInfo.isFile:
                self.getFile(child.getName()).refresh2()
                
    def _getFileStore(self):
        return self._workspace._storeManager.getFileStore(self)
    
    def _getResourceInfo(self):
        return self._workspace._getResourceInfo(self._path) 
    
class Container(Resource):
    def getDir(self,name):
        return Dir(self._path.append(name),self._workspace)
    
    def getFile(self,name):
        return File(self._path.append(name),self._workspace)
    
    def contains(self,name):
        return self._workspace.exists(self._path.append(name))
    
    def getChildren(self):
        return self._workspace._loadChildren(self)
    
class Dir(Container):
    def create(self):
        fileStore = self._workspace._storeManager.getFileStore(self)
        fileStore.makedir() 
        resourceInfo = _ResourceInfo.create(resource_type.DIR, fileStore.fetchInfo())
        self._workspace._create(self.getPath(),resourceInfo)
        return self
    
    def getType(self):
        return resource_type.DIR

class File(Resource):
    def create2(self,content):
        resourceInfo = self._workspace._storeManager.createFile(self,content)
        self._workspace._create(self.getPath(),resourceInfo)
        return self
    
    def create(self,content):
        fileStore = self._workspace._storeManager.getFileStore(self)
        fileStore.createFile(content) 
        resourceInfo = _ResourceInfo.create(resource_type.FILE, fileStore.fetchInfo())
        self._workspace._create(self.getPath(),resourceInfo)
        return self
    
    def getType(self):
        return resource_type.FILE

class RootResource(Container):
    def getProject(self,name):
        return Project(self._path.append(name),self._workspace)
    
    def getType(self):
        return resource_type.ROOT
    
    def refresh2(self):
        stores = self._workspace._storeManager.getProjectStores()
        for projectName,store in stores.items():
            self.getProject(projectName).refresh2()

class Project(Container):
    def create(self,projectAttributes):
        resourceInfo = self._workspace._storeManager.createProject(self,projectAttributes)
        self._workspace._create(self.getPath(),resourceInfo)
        return self
    
    def getType(self):
        return resource_type.PROJECT
    

    

                